package com.csap.framework.oauth2.server.service.impl;

import cn.dev33.satoken.code.TokenType;
import cn.dev33.satoken.config.SaTokenConfig;
import com.csap.framework.annotation.apidoc.Description;
import com.csap.framework.oauth2.server.entity.UserOpenInfoEntity;
import com.csap.framework.oauth2.server.model.UserOpenInfoModel;
import com.csap.framework.oauth2.server.mybatis.UserOpenInfoMapper;
import com.csap.framework.oauth2.server.service.UserOpenInfoService;
import com.csap.framework.util.Assert;
import com.csap.framework.util.exception.ExceptionUtils;
import com.csap.mybatisplus.extension.service.impl.BaseCsapServiceImpl;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.locks.Lock;

/**
 * <p>
 * 用户开放的相关信息
 * </p>
 *
 * @author yangchengfu
 * @dateTime 2021-07-27 10:03:58
 */
@Service
@Description(value = "用户开放的相关信息ServiceImpl")
public class UserOpenInfoServiceImpl extends BaseCsapServiceImpl<UserOpenInfoMapper, UserOpenInfoEntity, UserOpenInfoModel, Long> implements UserOpenInfoService {
    @Resource
    private RedisLockRegistry redisLockRegistry;
    @Resource
    private SaTokenConfig saTokenConfig;

    @Override
    public String containsOpenId(String clientId, String loginId) {
        Assert.notEmpty(clientId, "客户端ID不能为空");
        Assert.notEmpty(clientId, "用户ID不能为空");
        return lambdaQuery()
                .select(UserOpenInfoEntity::getOpenId)
                .eq(UserOpenInfoEntity::getClientId, clientId)
                .eq(UserOpenInfoEntity::getUserId, loginId)
                .oneOptional()
                .map(UserOpenInfoEntity::getOpenId)
                .get();
    }

    @Override
    public String getOpenId(String clientId, String loginId) {
        Lock lock = redisLockRegistry.obtain(String.format(saTokenConfig.getTokenName() + OPEN_LOCK_KEY, clientId, loginId));
        lock.lock();
        try {
            return lambdaQuery()
                    .select(UserOpenInfoEntity::getOpenId)
                    .eq(UserOpenInfoEntity::getClientId, clientId)
                    .eq(UserOpenInfoEntity::getUserId, loginId)
                    .oneOptional()
                    .when(Objects::isNull, i -> {
                        String string = TokenType.TIK.getBiFunction().apply(loginId, clientId);
                        super.insert(UserOpenInfoModel.builder().clientId(clientId).userId(loginId).openId(string).build());
                        return string;
                    }, UserOpenInfoEntity::getOpenId);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public String getUserId(String clientId, String openId) {
        Assert.notEmpty(clientId, "应用id不能为空");
        return lambdaQuery()
                .select(UserOpenInfoEntity::getUserId)
                .eq(UserOpenInfoEntity::getClientId, clientId)
                .eq(UserOpenInfoEntity::getOpenId, openId)
                .oneOptional()
                .isNullThrow(ExceptionUtils.mpe("当前用户未绑定OpendId"))
                .get()
                .getUserId();
    }
}
